#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>


//1.数组名的理解
//int main()
//{
//	int arr[10] = { 0 };
//	
//	int* p1 = arr;//数组名是数组首元素的地址
//	int* p3 = &arr[0];
//
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 0 };
//
//	printf("&arr[0]    = %p\n", &arr[0]);
//	printf("&arr[0]+1  = %p\n", &arr[0] + 1);
//
//	printf("arr        = %p\n", arr);
//	printf("arr+1      = %p\n", arr + 1);
//
//	printf("&arr       = %p\n", &arr);
//	printf("&arr+1     = %p\n", &arr + 1);
//
//	printf("siezeof(arr) = %zd\n", sizeof(arr));//如果arr代表数组首元素的地址，那应该输出的是4/8才对
//
//	return 0;
//}
/***********************************************
 * 其实数组名就是数组首元素（第一个元素）的地址，但是有两个例外
 * 1.sizeof(数组名)：sizeof中单独放数组名，这里的数组名表示整个数组，计算的是整个数组的大小。单位是字节
 * 2.&数组名，这里的数组名表示整个数组，取出的是整个数组的地址（整个数组的地址，和数组首元素的地址是有区别的，上面代码+1已经证明，&arr + 1之后地址会跨过40个字节）
 * 
 **********************************************/

//2.使用指针访问数组
// 原因 
// 1.数组在内存中连续储存
// 2.指针 + - 整数方便，可以获得每一个元素的值
//
//int main()
//{
//	int arr[10] = { 0 };
//	
//	//使用数组来访问数组
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	
//	//输入10个值
//	int* p = arr;
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		scanf("%d", p + i);//scanf本身就需要地址
//	}
//
//	//输出10个值
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 0 };
//
//	//使用数组来访问数组
//	int sz = sizeof(arr) / sizeof(arr[0]);
//
//	//输入10个值
//	int* p = arr;
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		scanf("%d", p + i);//scanf本身就需要地址//p + i == &arr[i]
//	}
//
//	//输出10个值
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", i[arr]);//p[i] == *(p + i) == arr[i] == *(arr+i)
//	}
//	return 0;
//}


/**************************************************************************************
* 3.一维数组传参的本质
* 
* 
**/



//void Print(int arr[10], int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(arr + i));
//	}
//}
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	
//	Print(arr, sz);
//	
//	return 0;
//}
//

/******************************************************************************************
* sz = 1?
* 数组传参的本质：数组名是首元素的地址，在数组传参的时候，传递的是数组名，也就是说，本质上数组传参的本质上传递的是首元素的地址
* 所以Print函数的形参理论上应该使用指针变量来接收首元素的地址。
* 在Print函数内部，写sizeof(arr)计算的是一个地址的大小（单位字节），而不是一个数组的大小（单位字节）
* 因为Print函数的参数部分是指针，所以在Print内部是无法计算数组大小的
* *********************************************************************************************
*/
//如果要求元素各数，在Print函数外求好传参即可
//1.数组传参的本质是传递了首元素的地址，所以形参访问的数组和实参的数组是相同的
//2.形参的数组不会再单独创建空间的，所以形参的数组可以省略数组大小

//冒泡排序：两两相邻的元素进行比较
//只能排序整型数组，字符串，结构体不可使用

//升序排序
//void bubble_sort(int arr[], int sz)
//{
//	int i = 0;
//	//趟数
//	for (i = 0; i < sz - 1; i++)
//	{
//		int j = 0;
//		for (j = 0; j < sz - 1 - i; j++)
//		{
//			//一趟的过程
//			if (arr[j] > arr[j + 1])
//			{
//				int temp = 0;
//				temp = arr[j];
//				arr[j] = arr[j + 1];
//				arr[j + 1] = temp;
//			}
//		}
//	}
//}
//
//
//void Print(int* arr, int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(arr + i));
//	}
//}
//int main()
//{
//	int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//
//	bubble_sort(arr, sz);
//	Print(arr, sz);
//
//	return 0;
//}


/*************************************优化（如果这个数组已经接近有序）****************************/
//void bubble_sort(int arr[], int sz)
//{
//	int i = 0;
//	//趟数
//	for (i = 0; i < sz - 1; i++)
//	{
//		int j = 0;
//		int flag = 1;//假设已经有序了
//		for (j = 0; j < sz - 1 - i; j++)
//		{
//			//一趟的过程
//			if (arr[j] > arr[j + 1])
//			{
//				int temp = 0;
//				temp = arr[j];
//				arr[j] = arr[j + 1];
//				arr[j + 1] = temp;
//				flag = 0;
//			}
//		}
//		if (flag == 1)//注意这个ifbreak需要是跳出趟数的循环
//		{
//			break;
//		}
//	}
//}
//
//
//void Print(int* arr, int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(arr + i));
//	}
//}
//int main()
//{
//	int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//
//	bubble_sort(arr, sz);
//	Print(arr, sz);
//
//	return 0;
//}

//二级指针
//指针变量也是变量，是变量就有地址，那指针变量的地址存放在哪里？？？-----二级指针
//int main()
//{
//	int a = 10;
//	int* p = &a;
//
//	int** pp = &p;
//	printf("%p\n", *pp);
//	printf("%p\n", &a);
//	printf("%d\n", **pp = 20);
//	printf("%d\n", a);
//	return 0;
//}

//用指针数组模拟二维数组

int main()
{
	int arr1[5] = { 1,2,3,4,5 };
	int arr2[5] = { 2,3,4,5,6 };
	int arr3[5] = { 3,4,5,6,7 };

	int* arr[] = { arr1, arr2, arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", *(*(arr + i) + j)); //arr[i][j]
		}
		printf("\n");
	}
	return 0;
}
//上述代码用指针模拟了二维数组的效果，实际上并非是指针，因为arr1,arr2,arr3并非是连续的
